/* 
 * fenv.h
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is a part of the clang port package.
 * No warranty is given; refer to the file DISCLAIMER within the package.
 *
 * Functions for testing character types and converting characters.
 *
 */

#ifndef _CLANG_PORT_FENV_H_
#define _CLANG_PORT_FENV_H_

/* All the headers include this file. */
#ifndef __IMPL_CLANG_PORT_API_
#	include <_clang_port.h>
#else
#	include <include/_clang_port.h>
#endif

#ifndef __IMPL_CLANG_PORT_API_
/* FPU status word exception flags */
#define FE_INVALID	0x01
#define FE_DENORMAL	0x02
#define FE_DIVBYZERO	0x04
#define FE_OVERFLOW	0x08
#define FE_UNDERFLOW	0x10
#define FE_INEXACT	0x20
#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO \
		       | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)

/* FPU control word rounding flags */
#define FE_TONEAREST	0x0000
#define FE_DOWNWARD	0x0400
#define FE_UPWARD	0x0800
#define FE_TOWARDZERO	0x0c00

/* The MXCSR exception flags are the same as the
   FE flags. */
#define __MXCSR_EXCEPT_FLAG_SHIFT 0

/* How much to shift FE status word exception flags
   to get the MXCSR exeptions masks,  */
#define __MXCSR_EXCEPT_MASK_SHIFT 7

/* How much to shift FE control word rounding flags
   to get MXCSR rounding flags,  */
#define __MXCSR_ROUND_FLAG_SHIFT 3

/*
  For now, support only for the basic abstraction of flags that are
  either set or clear. fexcept_t could be  structure that holds more
  info about the fp environment.
*/
typedef unsigned short fexcept_t;

/* This 32-byte struct represents the entire floating point
   environment as stored by fnstenv or fstenv, augmented by
   the  contents of the MXCSR register, as stored by stmxcsr
   (if CPU supports it). */
typedef struct
{
  unsigned short __control_word;
  unsigned short __unused0;
  unsigned short __status_word;
  unsigned short __unused1;
  unsigned short __tag_word;
  unsigned short __unused2;  
  unsigned int	 __ip_offset;    /* instruction pointer offset */
  unsigned short __ip_selector;  
  unsigned short __opcode;
  unsigned int	 __data_offset;
  unsigned short __data_selector;
  unsigned short  __unused3;
  unsigned int __mxcsr; /* contents of the MXCSR register  */
} fenv_t;


/*The C99 standard (7.6.9) allows us to define implementation-specific macros for
  different fp environments */
  
/* The default Intel x87 floating point environment (64-bit mantissa) */
#define FE_PC64_ENV ((const fenv_t *)-1)

/* The floating point environment set by MSVCRT _fpreset (53-bit mantissa) */
#define FE_PC53_ENV ((const fenv_t *)-2)

/* The FE_DFL_ENV macro is required by standard.
  fesetenv will use the environment set at app startup.*/
#define FE_DFL_ENV ((const fenv_t *) 0)
#endif // __IMPL_CLANG_PORT_API_

#ifdef __cplusplus
extern "C" {
#endif
/* 
 * Clang Port Api.
*/
/* 7.6.2 Exception */
typedef int CLANG_PORT_FPTR_TYPE(feclearexcept)(int);
extern CLANG_PORT_FPTR_VAR(feclearexcept);
typedef int CLANG_PORT_FPTR_TYPE(fegetexceptflag)(fexcept_t * flagp, int excepts);
extern CLANG_PORT_FPTR_VAR(fegetexceptflag);
typedef int CLANG_PORT_FPTR_TYPE(feraiseexcept)(int excepts );
extern CLANG_PORT_FPTR_VAR(feraiseexcept);
typedef int CLANG_PORT_FPTR_TYPE(fesetexceptflag)(const fexcept_t *, int);
extern CLANG_PORT_FPTR_VAR(fesetexceptflag);
typedef int CLANG_PORT_FPTR_TYPE(fetestexcept)(int excepts);
extern CLANG_PORT_FPTR_VAR(fetestexcept);
/* 7.6.3 Rounding */
typedef int CLANG_PORT_FPTR_TYPE(fegetround)(void);
extern CLANG_PORT_FPTR_VAR(fegetround);
typedef int CLANG_PORT_FPTR_TYPE(fesetround)(int mode);
extern CLANG_PORT_FPTR_VAR(fesetround);
/* 7.6.4 Environment */
typedef int CLANG_PORT_FPTR_TYPE(fegetenv)(fenv_t * envp);
extern CLANG_PORT_FPTR_VAR(fegetenv);
typedef int CLANG_PORT_FPTR_TYPE(fesetenv)(const fenv_t * );
extern CLANG_PORT_FPTR_VAR(fesetenv);
typedef int CLANG_PORT_FPTR_TYPE(feupdateenv)(const fenv_t *);
extern CLANG_PORT_FPTR_VAR(feupdateenv);
typedef int CLANG_PORT_FPTR_TYPE(feholdexcept)(fenv_t *);
extern CLANG_PORT_FPTR_VAR(feholdexcept);

#ifndef __IMPL_CLANG_PORT_API_
/*
 * STD C Api.
 */
/* 7.6.2 Exception */
CLANG_PORT_INLINE int  feclearexcept (int excepts)
{
	return CLANG_PORT_CALL_FPTR(feclearexcept)(excepts);
}
CLANG_PORT_INLINE int  fegetexceptflag (fexcept_t * flagp, int excepts)
{
	return CLANG_PORT_CALL_FPTR(fegetexceptflag)(flagp,excepts);
}
CLANG_PORT_INLINE int  feraiseexcept (int excepts )
{
	return CLANG_PORT_CALL_FPTR(feraiseexcept)(excepts);
}
CLANG_PORT_INLINE int  fesetexceptflag (const fexcept_t * flagp, int excepts)
{
	return CLANG_PORT_CALL_FPTR(fesetexceptflag)(flagp,excepts);
}
CLANG_PORT_INLINE int  fetestexcept (int excepts)
{
	return CLANG_PORT_CALL_FPTR(fetestexcept)(excepts);
}
/* 7.6.3 Rounding */
CLANG_PORT_INLINE int  fegetround (void)
{
	return CLANG_PORT_CALL_FPTR(fegetround)();
}
CLANG_PORT_INLINE int  fesetround (int mode)
{
	return CLANG_PORT_CALL_FPTR(fesetround)(mode);
}
/* 7.6.4 Environment */
CLANG_PORT_INLINE int  fegetenv (fenv_t * envp)
{
	return CLANG_PORT_CALL_FPTR(fegetenv)(envp);
}
CLANG_PORT_INLINE int  fesetenv (const fenv_t * envp)
{
	return CLANG_PORT_CALL_FPTR(fesetenv)(envp);
}
CLANG_PORT_INLINE int  feupdateenv (const fenv_t * envp)
{
	return CLANG_PORT_CALL_FPTR(feupdateenv)(envp);
}
CLANG_PORT_INLINE int  feholdexcept (fenv_t * envp)
{
	return CLANG_PORT_CALL_FPTR(feholdexcept)(envp);
}

#endif /* __IMPL_CLANG_PORT_API_ */

#ifdef __cplusplus
}
#endif

#endif /* ndef _CLANG_PORT_FENV_H_ */
